package com.cheng.admin.service.order.states;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.cheng.admin.constant.Constants;
import com.cheng.admin.dao.OrderMapper;
import com.cheng.admin.service.CouponService;
import com.cheng.admin.service.order.process.IOrderRollbackProcess;
import com.cheng.common.config.WeChatKeys;
import com.cheng.common.exception.CustomException;
import com.cheng.common.utils.WeChatUtils;
import com.ijpay.core.IJPayHttpResponse;
import com.ijpay.core.enums.RequestMethod;
import com.ijpay.core.kit.PayKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.core.utils.DateTimeZoneUtil;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.enums.WxApiType;
import com.ijpay.wxpay.enums.WxDomain;
import com.ijpay.wxpay.model.v3.Amount;
import com.ijpay.wxpay.model.v3.Payer;
import com.ijpay.wxpay.model.v3.UnifiedOrderModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Order(Constants.ORDER_STATUS_UNPAID)
@Service
@Slf4j
public class UnPaidState implements OrderState {
    @Autowired
    CouponService couponService;
    @Autowired
    Map<String, IOrderRollbackProcess> rollbackPreprocessMap;
    @Autowired
    OrderMapper orderMapper;
    @Autowired
    WeChatKeys weChatKeys;
    String serialNo;

    private String getSerialNumber() {
        if (StrUtil.isEmpty(serialNo)) {
            // 获取证书序列号
            X509Certificate certificate = PayKit.getCertificate(FileUtil.getInputStream(weChatKeys.getCertPath()));
            serialNo = certificate.getSerialNumber().toString(16).toUpperCase();
        }
        System.out.println("serialNo:" + serialNo);
        return serialNo;
    }

    @Override
    public String pay(Long id) throws Exception {
        com.cheng.admin.model.Order order = orderMapper.selectById(id);
        if (order == null) {
            throw new CustomException("订单已被取消");
        }
        //每次调用支付需要刷新订单号
        order.setOrderNo("S20" + new Date().getTime());
        String timeExpire;
        timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3);
        JSONObject session = WeChatUtils.getSession();
        String openId = (String) session.get("openid");
        UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel()
                .setAppid(weChatKeys.getAppId())
                .setMchid(weChatKeys.getMchId())
                .setDescription("用户" + order.getUserId() + ": " + order.getType())
                .setOut_trade_no(order.getOrderNo())
                .setTime_expire(timeExpire)
                .setAttach("www.jarcheng.top")
                .setNotify_url(weChatKeys.getNotifyUrl())
                .setAmount(new Amount().setTotal(order.getFinalPrice().multiply(BigDecimal.valueOf(100)).intValue()))
                .setPayer(new Payer().setOpenid(openId));
        log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
        IJPayHttpResponse response = WxPayApi.v3(
                RequestMethod.POST,
                WxDomain.CHINA.toString(),
                WxApiType.JS_API_PAY.toString(),
                weChatKeys.getMchId(),
                getSerialNumber(),
                null,
                weChatKeys.getKeyPath(),
                JSONUtil.toJsonStr(unifiedOrderModel)
        );
        log.info("统一下单响应 {}", response);
        if (response.getStatus() == 200) {
            // 根据证书序列号查询对应的证书来验证签名结果
            boolean verifySignature = WxPayKit.verifySignature(response, weChatKeys.getPlatformCertPath());
            log.info("verifySignature: {}", verifySignature);
            if (verifySignature) {
                orderMapper.updateById(order);
                String body = response.getBody();
                cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(body);
                String prepayId = jsonObject.getStr("prepay_id");
                Map<String, String> map = WxPayKit.jsApiCreateSign(weChatKeys.getAppId(), prepayId, weChatKeys.getKeyPath());
                log.info("唤起支付参数:{}", map);
                return JSONUtil.toJsonStr(map);
            }
        }
        return JSONUtil.toJsonStr(response);

    }

    @Override
    public Map<String, String> cancel(Long id) {
        com.cheng.admin.model.Order order = orderMapper.selectById(id);
        if (order == null) {
            throw new CustomException("订单已取消");
        }
        if (order.getPaymentTime() != null) {
            throw new CustomException("订单已支付无法取消");
        }
        if (!order.getUserId().equals(StpUtil.getLoginIdAsLong()) && !StpUtil.hasRole("admin")) {
            throw new CustomException("非本人操作");
        }
        couponService.rollbackPreprocess(order);
        IOrderRollbackProcess rollbackPreprocessService = rollbackPreprocessMap.get(order.getType());
        if (rollbackPreprocessService != null) {
            rollbackPreprocessService.rollbackPreprocess(order);
        }
        orderMapper.deleteById(id);
        HashMap<String, String> result = new HashMap<>();
        result.put("result", "success");
        return result;
    }

    @Override
    public Map<String, String> ship(Long id, String logisticsNo) {
        throw new CustomException("未付款无法发货");
    }

    @Override
    public Map<String, String> confirm(Long id) {
        throw new CustomException("未付款无法确认收货");
    }
}
